<script setup lang="ts">
import type { ComponentPublicInstance, PropType, VNodeRef } from 'vue'
import type { CategoryItem } from '~/api/category'

defineProps({
  data: {
    type: Array as PropType<CategoryItem[]>,
    required: true,
  },
})

let lock = false

const sliderRef = ref<HTMLLIElement | null>(null)

const sliderStyle = ref<{ transform?: string; width?: string }>({})

const currentCategoryIndex = ref<number>(0)

// 获取v-for循环的所有ref
let lis: Array<Element | ComponentPublicInstance> = []
// 函数会在dom变化时重复执行！！
const lisRef: VNodeRef = (ref) => {
  if (ref)
    lis.push(ref)
}

const ulRef = ref<HTMLUListElement | null>(null)

// 通过 vueuse => useScroll获取响应式scroll滚动距离
const { x: ulLeftScroll } = useScroll(ulRef)

// NOTE: 解决课程中的一个bug（无法一开始就计算第一个元素的宽度）
// 会在 lisRef 触发后执行
onUpdated(() => {
  if (!lock) {
    lock = true
    const { left, width } = (lis[0] as Element).getBoundingClientRect()

    sliderStyle.value = {
      transform: `translateX(${ulLeftScroll.value + left - 10}px)`,
      width: `${width}px`,
    }
  }
})

// 数据改变后，dom变化前
onBeforeUpdate(() => {
  // 重新将数组重置
  lis = []
})

// 监听分类点击从而应用新的样式
watch(currentCategoryIndex, async (newVal) => {
  // 单元测试编写需要！！（参照element-plus tabs组件的测试用例编写）
  await nextTick()

  const { left, width } = (lis[newVal] as Element).getBoundingClientRect()

  sliderStyle.value = {
    transform: `translateX(${ulLeftScroll.value + left - 10}px)`,
    width: `${width}px`,
  }
})

const onItemClick = (index: number) => {
  currentCategoryIndex.value = index
}

const isVisable = ref(false)
</script>

<template>
  <div v-if="data && data.length" class="bg-white sticky top-0 left-0 z-10">
    <ul ref="ulRef" class="relative flex overflow-x-auto p-1 text-xs text-zinc-600 overflow-hidden">
      <!-- 滑块 -->
      <li ref="sliderRef" :style="sliderStyle" class="absolute h-[22px] bg-zinc-900 rounded-lg duration-200" />
      <!-- 汉堡按钮 -->
      <li class="fixed shadow-l-white top-0 right-[-1px] h-4 px-1 flex items-center bg-white z-20" @click="isVisable = true">
        <SvgIcon class="w-1.5 h-1.5" name="hamburger" />
      </li>
      <!-- 分类元素 -->
      <li v-for="(item, index) in data" :ref="lisRef" :key="item.id" :class="{ 'text-zinc-100': currentCategoryIndex === index }" class="shrink-0 px-1.5 py-0.5 z-10 duration-200 last:mr-4" @click="onItemClick(index)">
        {{ item.name }}
      </li>
    </ul>
    <Popup v-model="isVisable" :append-to-body="true">
      <div>
        我是内容
      </div>
    </Popup>
  </div>
</template>
